package cn.big.bigd.biocode.configure;


import cn.big.bigd.biocode.service.UserService;
import org.jasig.cas.client.session.SingleSignOutFilter;
import org.jasig.cas.client.validation.Cas20ServiceTicketValidator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.cas.ServiceProperties;
import org.springframework.security.cas.authentication.CasAuthenticationProvider;
import org.springframework.security.cas.web.CasAuthenticationEntryPoint;
import org.springframework.security.cas.web.CasAuthenticationFilter;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.AuthenticationUserDetailsService;
import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import java.util.UUID;

/**
 * @ClassName: SecurityConfigure
 * @Description: TODO
 * @Author: FanWang
 * @CreateDate: 2017/11/24 下午3:05
 * @Version: 1.0
 * @Copyright: Copyright (c) 2018/11/24
 **/
@Configuration
@EnableWebSecurity
@Order(2)
public class SecurityConfigure extends WebSecurityConfigurerAdapter {
    


    @Value("${app.host}")
    private String host;

    @Value("${app.service.security}")
    private String APP_SERVICE_URL;
    @Value("${cas.service.prefix}")
    private  String CASSERVER;

    @Value("${cas.service.login}")
    private String CAS_URL_LOGIN;

    @Value("${cas.service.logout}")
    private String CAS_URL_LOGOUT;

    /**指定service相关信息 单点登出过滤器*/
    @Bean
    public ServiceProperties serviceProperties() {
        ServiceProperties serviceProperties = new ServiceProperties();
        // 验证ST的CAS server url：被CasAuthenticationFilter监听的URL
        serviceProperties.setService(APP_SERVICE_URL);
        // sendRenew默认是false，true则意味着不允许单点登录，用户需要重新输入用户名密码以验证
        serviceProperties.setSendRenew(false);
        return serviceProperties;
    }
    /**cas 认证 Provider*/
    @Bean
    public CasAuthenticationProvider casAuthenticationProvider() {
        CasAuthenticationProvider casAuthenticationProvider = new CasAuthenticationProvider();
        casAuthenticationProvider.setAuthenticationUserDetailsService(authenticationUserDetailsService());
        casAuthenticationProvider.setServiceProperties(serviceProperties());
        casAuthenticationProvider.setTicketValidator(cas20ServiceTicketValidator());
        // key is an_id_for_this_auth_provider_only，这个大概就是...
        String key = UUID.randomUUID().toString();
        System.out.println("----------------CasAuthenticationProvider的key是："+key);
        casAuthenticationProvider.setKey(key);
        return casAuthenticationProvider;
    }
    @Bean
    public AuthenticationUserDetailsService authenticationUserDetailsService() {
        return new UserService();
    }
    @Bean
    public Cas20ServiceTicketValidator cas20ServiceTicketValidator() {
        return new Cas20ServiceTicketValidator(CASSERVER);
    }

    @Bean
    public CasAuthenticationFilter casAuthenticationFilter() throws Exception {
        CasAuthenticationFilter casAuthenticationFilter = new CasAuthenticationFilter();
        casAuthenticationFilter.setAuthenticationManager(authenticationManager());
        return casAuthenticationFilter;
    }
    /**认证的入口*/
    @Bean
    public CasAuthenticationEntryPoint casAuthenticationEntryPoint() {
        CasAuthenticationEntryPoint casAuthenticationEntryPoint = new CasAuthenticationEntryPoint();
        casAuthenticationEntryPoint.setLoginUrl(CAS_URL_LOGIN);
        casAuthenticationEntryPoint.setServiceProperties(serviceProperties());
        return casAuthenticationEntryPoint;
    }


    @Bean
    public SingleSignOutFilter singleSignOutFilter() {
        SingleSignOutFilter singleSignOutFilter = new SingleSignOutFilter();
        singleSignOutFilter.setCasServerUrlPrefix(CASSERVER);
        singleSignOutFilter.setIgnoreInitConfiguration(true);
        return singleSignOutFilter;
    }

    /**请求单点退出过滤器*/
    @Bean
    public LogoutFilter requestCasGlobalLogoutFilter() {
        LogoutFilter logoutFilter = new LogoutFilter(CAS_URL_LOGOUT + "?service="
                +host, new SecurityContextLogoutHandler());
        // logoutFilter.setFilterProcessesUrl("/logout");
        //  logoutFilter.setFilterProcessesUrl("/j_spring_cas_security_logout");
        logoutFilter.setLogoutRequestMatcher(new AntPathRequestMatcher("/logout", "GET"));
        return logoutFilter;
    }



/*
    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    PasswordEncoder getPasswordEncoder() {

        return new BCryptPasswordEncoder();
        //  return new Md5PasswordEncoder();
    }*/

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
       /* auth.userDetailsService(userService).passwordEncoder(getPasswordEncoder())
                .and();*/
        auth
                .authenticationProvider(casAuthenticationProvider());

    }

    /**
     * 暂时没用上
     * @param web
     * @throws Exception
     */
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/static/**");
    }

/*
    @Autowired
    private CustomAuthenticationSuccessHandler customAuthenticationSuccessHandler;

*/

//    @Override
//    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
////        super.configure(auth);
//        auth.authenticationProvider(casAuthenticationProvider());
//    }


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.headers().frameOptions().sameOrigin();
        http.exceptionHandling()
                .authenticationEntryPoint(casAuthenticationEntryPoint()).and()
                .addFilter(casAuthenticationFilter())
                .addFilterBefore(singleSignOutFilter(), CasAuthenticationFilter.class)
                .addFilterBefore(requestCasGlobalLogoutFilter(), LogoutFilter.class);
        http.authorizeRequests()
                .antMatchers("/dba/**").hasAuthority("DBA")
                .antMatchers("/admin/**").hasAnyAuthority("ADMIN", "DBA")
                .antMatchers("/curator/**").hasAnyAuthority("ADMIN", "CURATOR", "DBA")
                .antMatchers("/user/**").hasAnyAuthority("ADMIN", "CURATOR", "DBA", "USER")
                .antMatchers("/login").hasAnyAuthority("ADMIN", "CURATOR", "DBA", "USER")
                .antMatchers("/**/**edit").hasAnyAuthority("ADMIN",  "DBA", "USER")
                .antMatchers("/**/**save").hasAnyAuthority("ADMIN",  "DBA", "USER")
                .antMatchers("/**").permitAll()
//                .and()
//                .formLogin().successHandler(customAuthenticationSuccessHandler)
//                .usernameParameter("email")
//                .loginPage("/login")
//                .permitAll()
                .and().csrf().disable();
//        http.logout().logoutSuccessUrl("/").invalidateHttpSession(true).deleteCookies();
    }
}

